from unicodedata import name
from flask import g
from vsearcher import VSearcher
from app.models.course import Course
from app.libs.forms import CreateResourcePureForm, ResourceByIDForm, GetResourceListForm, SearchForm, UploadByPathForm
from app.service.chapter import ChapterService
from app.vo import SCourseVO
from .base import BaseService
from vsearcher._core import vo as vs_vo


class CourseService(BaseService):
    """
        功能：
        1. 获取目录结构
        2. 获取不带视频信息
    """

    @classmethod
    def get_by_id(cls, form: ResourceByIDForm) -> Course:
        course_id = form.data.get('id')
        return cls.optional_404(Course.current_user_filter(Course.id == course_id).first())

    @classmethod
    def create_pure(cls, form: CreateResourcePureForm) -> Course:
        with Course.auto_commit() as context:
            course_name = form.name.data
            # 记录重名的解决方案，@WAIT 可以尝试编写 数据库的触发器和函数，处理更佳
            course_count = Course.current_user_filter(
                Course.name.like(f'{course_name}%')
            ).count()
            if course_count > 0:
                course_name = f'{course_name}_{course_count}'

            new_course = Course(
                name=course_name,
                user_id=g.current_user.id,
                output_dir=VSearcher.createCourseDir(course_name)
            )
            context.session.add(new_course)
        return new_course

    @classmethod
    def save2db(cls, vs_course_vo: vs_vo.CourseVO):
        new_course = Course().set_attr(vs_course_vo, filter_keys=[
            'id', 'chapters'])  # id数据库自增长，不需要设置, @RISK 设置容易报错
        new_course.user_id = g.current_user.id
        Course.session.add(new_course)
        Course.session.flush()  # commit后获取新章节ID
        for vs_chapter_vo in vs_course_vo.chapters:
            ChapterService.save2db(
                vs_chapter_vo, course_id=new_course.id)  # 存储章节信息
        return new_course

    @classmethod
    def upload_by_path(cls, form: UploadByPathForm):
        with Course.auto_commit():  # @WAIT 写一个自定义注解获取更好
            course_dir_path = form.path.data
            vs_course_vo = VSearcher.executeCourse(
                course_dir_path,
                step=form.vsConfigForm.step.data,
                speed_x=form.vsConfigForm.speed.data
            )
            return cls.save2db(vs_course_vo)

    @classmethod
    def searchByForm(cls, form: SearchForm) -> SCourseVO:
        course = cls.optional_404(
            Course.current_user_filter(Course.id == form.id.data).first()
        )
        return cls.search(form.key.data, course)

    @classmethod
    def search(cls, key, course: Course) -> SCourseVO:
        chapters_search_result = []
        for chapter in course.chapters:
            vs_chapter_search_result = ChapterService.search(key, chapter)
            if vs_chapter_search_result.videos:
                chapters_search_result.append(vs_chapter_search_result)
        # course.chapters = chapters_search_result # 这样赋值不被允许
        s_course_vo = SCourseVO(course)
        s_course_vo.chapters = chapters_search_result
        return s_course_vo

    @classmethod
    def gets(cls, form: GetResourceListForm):
        return Course.current_user_filter().offset(form.pager.offset).limit(form.pager.limit).all(), form.pager

    @classmethod
    def del_by_id(cls, form: ResourceByIDForm):
        # @RISK 如果一个视频属于某个Chapter 或者 Source 还要更新pickle对象中的内容, 比如删除了某一个上街
        # @WAIT vsearch 支持, 删除某个课程中的某个内容
        course = cls.optional_404(Course.current_user_filter(
            Course.id == form.id.data).first())
        with Course.auto_commit() as context:
            for chapter in course.chapters:
                for video in chapter.videos:
                    context.session.delete(video)
                context.session.delete(chapter)
            context.session.delete(course)
            VSearcher.releaseByOutputDir(course.output_dir)  # 删除对象的处理结果： 包括：图片
            return course
